package com.heng.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.hutool.core.bean.BeanUtil;
import com.heng.dao.entity.Order;
import com.heng.dao.entity.ShippingAddress;
import com.heng.dao.mapper.OrderMapper;
import com.heng.dto.CreateOrderDTO;
import com.heng.dto.OrderResponseVO;
import com.heng.dto.OrderStatusVO;
import com.heng.exception.BusinessException;
import com.heng.service.OrderService;
import com.heng.service.ShippingAddressService;
import com.heng.utils.OrderNoGenerator;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;

@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Resource
    private ShippingAddressService shippingAddressService;

    @Resource
    private OrderNoGenerator orderNoGenerator;

    /**
     * 核心逻辑：支付成功后创建订单（事务保证原子性）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public OrderResponseVO createPaySuccessOrder(CreateOrderDTO dto, Long userId) {
        // 1. 校验收货地址（如果是新增地址，先保存；如果是已有地址，校验归属）
        Long addressId = saveOrCheckAddress(dto, userId);

        // 2. 生成唯一订单号
        String orderNo = orderNoGenerator.generate();

        // 3. 计算优惠金额（原价-实付）
        BigDecimal discountAmount = dto.getOriginalAmount().subtract(dto.getPayAmount());

        // 4. 构建订单实体
        Order order = new Order();
        order.setOrderNo(orderNo);
        order.setUserId(userId);
        order.setProductId(dto.getProductId());
        order.setCouponId(dto.getCouponId() == null ? 0L : dto.getCouponId());
        order.setPayAmount(dto.getPayAmount());
        order.setCreateTime(LocalDateTime.now());
        order.setUpdateTime(LocalDateTime.now());
        order.setOriginalAmount(dto.getOriginalAmount());
        order.setDiscountAmount(discountAmount);
        order.setPayType(dto.getPayType());
        order.setOrderStatus("PAY_SUCCESS"); // 支付成功状态
        order.setShippingAddressId(addressId);

        // 5. 保存订单（MyBatis-Plus自带save方法）
        try {
            boolean saveSuccess = save(order);
            if (!saveSuccess) {
                throw new BusinessException("订单创建失败，请重试");
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }


        // 6. 后续扩展：更新商品库存、优惠券状态（假设已有对应Service）
        // productService.decreaseStock(dto.getProductId(), 1);
        // if (dto.getCouponId() != null && dto.getCouponId() != 0) {
        //     couponService.markUsed(dto.getCouponId(), userId);
        // }

        // 7. 构建并返回响应
        OrderResponseVO response = new OrderResponseVO();
        BeanUtil.copyProperties(order, response);
        // 关联地址信息返回
        ShippingAddress address = shippingAddressService.getById(addressId);
        response.setReceiverName(address.getReceiverName());
        response.setReceiverPhone(address.getReceiverPhone());
        response.setFullAddress(String.format("%s%s%s%s", address.getProvince(), address.getCity(), address.getDistrict(), address.getDetailAddress()));

        return response;
    }

    /**
     * 保存新地址或校验已有地址归属
     */
    private Long saveOrCheckAddress(CreateOrderDTO dto, Long userId) {
        // 情况1：前端传递地址ID（使用已有地址）
        if (dto.getAddressId() != null) {
            ShippingAddress address = shippingAddressService.getById(dto.getAddressId());
            if (address == null) {
                throw new BusinessException("收货地址不存在");
            }
            if (!address.getUserId().equals(userId)) {
                throw new BusinessException("无权使用该收货地址");
            }
            return dto.getAddressId();
        }

        // 情况2：前端传递完整地址信息（新增地址）
        if (dto.getReceiverName() == null || dto.getReceiverPhone() == null ||
            dto.getProvince() == null || dto.getCity() == null || dto.getDistrict() == null || dto.getDetailAddress() == null) {
            throw new BusinessException("新增地址信息不完整");
        }

        ShippingAddress newAddress = new ShippingAddress();
        newAddress.setUserId(userId);
        newAddress.setReceiverName(dto.getReceiverName());
        newAddress.setReceiverPhone(dto.getReceiverPhone());
        newAddress.setProvince(dto.getProvince());
        newAddress.setCity(dto.getCity());
        newAddress.setDistrict(dto.getDistrict());
        newAddress.setDetailAddress(dto.getDetailAddress());
        newAddress.setIsDefault(0); // 默认为非默认地址

        boolean saveSuccess = shippingAddressService.save(newAddress);
        if (!saveSuccess) {
            throw new BusinessException("收货地址保存失败");
        }
        return newAddress.getId();
    }


    /**
     * 核心逻辑：查询订单状态 + 权限校验
     */
    @Override
    public OrderStatusVO getOrderStatusByNo(String orderNumber, Long userId) {
        // 1. 根据订单号查询订单（订单号唯一，用selectOne）
        LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Order::getOrderNo, orderNumber);
        Order order = this.getOne(queryWrapper);

        // 2. 订单不存在：返回待支付（前端可能刚创建订单，后端还未同步状态）
        if (order == null) {
            OrderStatusVO vo = new OrderStatusVO();
            vo.setStatus("PAY_SUCCESS"); // 支付成功
            vo.setFailReason("");
            return vo;
        }

        // 3. 权限校验：确保订单属于当前用户（防止越权查询他人订单）
        if (!order.getUserId().equals(userId)) {
            throw new BusinessException("无权查询该订单状态");
        }

        // 4. 组装状态响应
        OrderStatusVO vo = new OrderStatusVO();
        vo.setStatus(order.getOrderStatus());

        // 5. 支付失败时补充原因（根据实际业务场景扩展，这里模拟常见原因）
        if ("PAY_FAILED".equals(order.getOrderStatus())) {
            String failReason = "未知支付失败";
            // 可根据订单表扩展字段（如 fail_reason）存储具体原因，这里简化处理
            if (order.getPayAmount().compareTo(order.getOriginalAmount()) < 0) {
                failReason = "优惠已过期";
            } else if (order.getProductId() == null) {
                failReason = "商品不存在";
            }
            vo.setFailReason(failReason);
        } else {
            vo.setFailReason(""); // 非失败状态，原因为空
        }

        return vo;
    }
}